﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Client
{
    public partial class Client : Form
    {
        private Socket _client;
        public Client()
        {
            InitializeComponent();
            //关闭跨线程访问检查
            CheckForIllegalCrossThreadCalls = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //1.创建客户端套接字，使用IPV4，字节流，TCP协议
            _client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //2.客户端连接到服务端
            _client.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text)));
            textBox3.AppendText("客户端连接到了服务端");

            button1.Enabled = false;

            //请求刷新一下客户端列表
            byte[] refreshRequest = { 4 };
            _client.Send(refreshRequest);

            //用子线程来接受服务端发来的消息
            Thread thread = new Thread(RecvMsg);
            thread.IsBackground = true;
            //由于这里的SaveFileDialog 由主线程创建，主线程为ApartmentState.STA，只能主线程操作。
            //子线程设置为ApartmentState.STA，允许子线程操作。
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            //发送消息给指定客户端
            string targetClient = comboBox1.Text;
            string message = textBox4.Text;
            byte[] targetClientBytes = Encoding.UTF8.GetBytes(targetClient);
            byte[] messagesBytes = Encoding.UTF8.GetBytes(message);
            byte[] buffer = new byte[targetClientBytes.Length + messagesBytes.Length + 2];

            buffer[0] = 1;
            buffer[1] = (byte)targetClientBytes.Length;

            Array.Copy(targetClientBytes, 0, buffer, 2, targetClientBytes.Length);
            Array.Copy(messagesBytes, 0, buffer, 2 + targetClientBytes.Length, messagesBytes.Length);

            _client.Send(buffer);
            textBox4.Clear();
        }

        private void RecvMsg()
        {
            try
            {
                //需要循环接收
                while (true)
                {
                    //5.阻塞等待服务端发来的消息
                    byte[] buffer = new byte[1024];
                    int length = _client.Receive(buffer);
                    switch (buffer[0])
                    {
                        case 1:
                            int targetClientLength = buffer[1];
                            int startIndex = 2;
                            string sourceClient = Encoding.UTF8.GetString(buffer, startIndex, targetClientLength);
                            string message = Encoding.UTF8.GetString(buffer, startIndex + targetClientLength, length - (startIndex + targetClientLength));
                            textBox3.AppendText("\r\n" + sourceClient + ": " + message);
                            break;
                        case 2:
                            DialogResult dialogResult = MessageBox.Show("对方向你放松的文件，是否接收？", "收到了文件", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                            if (dialogResult == DialogResult.OK)
                            {
                                //1.创建保存文件对话框对象
                                SaveFileDialog ofd = new SaveFileDialog();

                                //设置文件对话框标题
                                ofd.Title = "请选择保存的位置";

                                //设置访问的文件夹路径
                                ofd.InitialDirectory = "D:\\";

                                //设置文件过滤器
                                ofd.Filter = "文本文件|*.txt|视频|*.mp4|其它|*.*";

                                //2.展示保存文件对话框
                                if (ofd.ShowDialog() == DialogResult.OK)
                                {
                                    //3.获取保存的文件及文件名
                                    string fileName = ofd.FileName;

                                    if (!string.IsNullOrEmpty(fileName))
                                    {
                                        //4.将接收到的文件内容添加到文件中去
                                        using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
                                        {
                                            fs.Write(buffer, 2, length - 2);
                                        }
                                    }
                                }
                            }
                            break;
                        case 3:
                            Point location = this.Location;

                            for (int i = 0; i < 200; i++)
                            {
                                this.Location = new Point(location.X, location.Y + 5);
                                this.Location = new Point(location.X, location.Y - 5);
                            }
                            break;
                        case 4:
                            string clientList = Encoding.UTF8.GetString(buffer, 1, length - 1);
                            string[] clients = clientList.Split('|');
                            foreach (string client in clients)
                            {
                                if (!string.IsNullOrEmpty(client) && !comboBox1.Items.Contains(client))
                                {
                                    comboBox1.Items.Add(client);
                                }
                            }
                            break;
                        case 5:
                            // 处理客户端掉线信息
                            string disconnectedClient = Encoding.UTF8.GetString(buffer, 1, buffer.Length - 1);
                            if (comboBox1.Items.Contains(disconnectedClient))
                            {
                                comboBox1.Items.Remove(disconnectedClient);
                            }
                            break;
                    }

                }


            }
            catch (SocketException ex)
            {
                textBox4.AppendText("\r\n" + _client.RemoteEndPoint + ": 服务端掉线了");
                button1.Enabled = true;
            }
        }
    }
}
